﻿using RabbitMQ.Client;
using System;
using System.Data.Common;
using Utility.Global.Exceptions;

namespace Utility.RabbitMQ_Service.Implementations
{
    public class RabbitMQServiceImpl : RabbitMQService
    {
        private IConnection connection = null;

        public RabbitMQServiceImpl(ConnectionFactory connectionFactory)
        {
            this.Connect(connectionFactory);
        }

        public static RabbitMQService CreateRabbitMQService()
        {
            DbConnectionStringBuilder dbConnectionStringBuilder = GetDatabaseConnectionString();

            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.HostName = dbConnectionStringBuilder["hostname"].ToString();
            connectionFactory.UserName = dbConnectionStringBuilder["username"].ToString();
            connectionFactory.Password = dbConnectionStringBuilder["password"].ToString();

            return new RabbitMQServiceImpl(connectionFactory);
        }

        private static DbConnectionStringBuilder GetDatabaseConnectionString()
        {
            System.Configuration.ConnectionStringSettings connectionSettings = System.Configuration.ConfigurationManager.ConnectionStrings["RabbitMQ"];
            if (connectionSettings == null)
            {
                throw new TechnicalProblemException("RabbitMQ muss in der App.config konfiguriert sein.");
            }

            DbConnectionStringBuilder dbConnectionStringBuilder = new DbConnectionStringBuilder();
            dbConnectionStringBuilder.ConnectionString = connectionSettings.ConnectionString;
            return dbConnectionStringBuilder;
        }

        public void Close()
        {
            try
            {
                connection.Close();
            }
            catch (Exception ex)
            {
                throw new TechnicalProblemException("Verbindung zum RabbitMQ konnte nicht geschlossen werden.", ex);
            }
        }

        private void Connect(ConnectionFactory connectionFactory)
        {
            try
            {
                this.connection = connectionFactory.CreateConnection();
            }
            catch (Exception ex)
            {
                throw new TechnicalProblemException("Verbindung zum RabbitMQ konnte nicht hergestellt werden.", ex);
            }
        }
        
        public RabbitMQQueue<T> NewRabbitMQQueue<T>(string queueName) where T : class
        {
            try
            {
                return new RabbitMQQueueImpl<T>(this.connection, queueName);
            }
            catch (Exception ex)
            {
                throw new TechnicalProblemException("Queue konnte nicht angelegt werden.", ex);
            }
        }

        public void Dispose()
        {
            this.Close();
        }
    }
}
